package edu.utdallas.taskExecutor;

import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;

public class BlockingQueueComet {

    // Hold the objects 
    private ArrayList<Task> queue;
    
    // Set initial Limit
    private int limit = 10;
    
    // Semaphores to control input and output
    Semaphore put_sema;
    Semaphore add_sema;
    Semaphore take_sema;

    public BlockingQueueComet(int limit) {
        queue = new ArrayList<Task>();
        
        add_sema = new Semaphore(1, true);
        take_sema = new Semaphore(1, true);
        put_sema = new Semaphore(1, true);
        
        this.limit = limit;
        try {
            // Hold the take_sema until something puts
            take_sema.acquire();
        } catch (InterruptedException ex) {
            Logger.getLogger(BlockingQueueComet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void put(Object item) throws InterruptedException {  
        

        
        add_sema.acquire();
        //  Wait for there to be space in the queue
        while(queue.size() == this.limit) {
            put_sema.acquire();
        }
        queue.add((Task) item);

        
        // Notify a thread waiting to take a task
        if(queue.size() == 1) {
            take_sema.release();
        }
        add_sema.release();
    }

    public synchronized Task take() throws InterruptedException {

        // Temporary task to return
        Task task;
        
        while(queue.isEmpty()) {
            // Wait for the queue to contain an object
            take_sema.acquire();
        }

        task = (Task)queue.remove(0);
        
        // Notify thread waiting to put a thread into the queue
        if(queue.size() == (limit-1)){
            put_sema.release();
        }
        
        return task;
    }
}
